package com.gba.mark.origin.service.impl;

import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gba.mark.action.mapper.ActionMapper;
import com.gba.mark.article.mapper.ArticleMapper;
import com.gba.mark.exam.entity.ExamResult;
import com.gba.mark.exam.mapper.ExamReusltMapper;
import com.gba.mark.group.entity.Group;
import com.gba.mark.group.mapper.GroupMapper;
import com.gba.mark.group.service.IGroupService;
import com.gba.mark.labelResult.entity.LabelResult;
import com.gba.mark.labelResult.entity.dto.LabelResultDTO;
import com.gba.mark.labelResult.mapper.LabelResultMapper;
import com.gba.mark.labelResult.service.ILabelResultService;
import com.gba.mark.origin.entity.OriginStatus;
import com.gba.mark.origin.entity.dto.OriginDTO;
import com.gba.mark.origin.mapper.OriginMapper;
import com.gba.mark.origin.entity.Origin;
import com.gba.mark.origin.service.IOriginService;
import com.gba.mark.user.entity.permission.UserRole;
import com.gba.mark.user.entity.user.User;
import com.gba.mark.user.mapper.permission.UserRoleMapper;
import com.gba.mark.user.service.user.IUserService;
import com.gba.mark.util.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class OriginServiceImpl extends ServiceImpl<OriginMapper, Origin> implements IOriginService {

    @Resource
    private RedisTemplate<String, Integer> redisTemplate;

    @Resource
    private OriginMapper originMapper;

    @Resource
    private LabelResultMapper labelResultMapper;

    @Resource
    private IGroupService groupService;

    @Resource
    private GroupMapper groupMapper;

    @Resource
    private ExamReusltMapper examReusltMapper;

    @Resource
    private ArticleMapper articleMapper;

    @Resource
    private IOriginService originService;

    @Resource
    private ILabelResultService labelResultService;

    @Resource
    private IUserService userService;

    @Resource
    private ActionMapper actionMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    //    @Scheduled(cron = "0 0 4 ? * *")
    @Override
    public void initOriginRedis(int userId, int groupId) {
        System.out.println(new Date() + ": initOriginRedis start!");
        //开始时间
        long start = System.currentTimeMillis();
        //redis总条数
        int full = 300;
        try {
            List<Integer> articleIdList = articleMapper.getArticleIdList(groupId);
            for (Integer list : articleIdList) {
                int size = Math.toIntExact(redisTemplate.opsForList().size(userId + "_" + groupId));
                List<Integer> originIdList = originMapper.getOriginIdList(full - size, list);
                if (full - size == 0) {
                           break;
                        }else {
                            for(Integer list2 : originIdList){
                                redisTemplate.opsForList().rightPush(userId + "_" + groupId, list2);
                            }
                        }
                    }

            long end = System.currentTimeMillis();
            System.out.println(new Date() + ": initOriginRedis is OK! (" + (end - start) / 60000 + " min)");

        } catch (RuntimeException e) {
            e.printStackTrace();
            long end = System.currentTimeMillis();
            System.out.println(new Date() + ": initOriginRedis is failed! (" + (end - start) / 60000 + " min)");
        }

    }


    @Override
    public ResponseUtil<JSONObject> getOrigin(int userId, int groupId) {

        JSONObject result = new JSONObject();
        OriginDTO originDTO = new OriginDTO();

        //判断是组长还是组员
        if (groupMapper.selectOne(new QueryWrapper<Group>()
                .eq("id", groupId)
                .eq("admin_id", userId)) != null ||
                //判断组员是否考过试，考过则给分配语料
                examReusltMapper.selectOne(new QueryWrapper<ExamResult>()
                        .eq("user_id", userId)
                        .eq("group_id", groupId)) != null) {

            Integer originId = redisTemplate.opsForList().leftPop(userId + "_" + groupId);
            if (originId != null) {
                //通过id查询返回原语料
                Origin origin = originService.getOne(new QueryWrapper<Origin>().eq("id", originId)
                        .eq("active",true));
                if(origin != null && origin.getStatus() < OriginStatus.MARK_MAX.getData()){
                    //上锁任务
                    originMapper.lockOrigin(originId);


                    List<LabelResult> labelResultList = labelResultMapper.selectList(new QueryWrapper<LabelResult>()
                            .eq("origin_id", originId));

                    //result.put("origin",labelResultList);
                    //通过userid查询username
                    User user = userService.getOne(new QueryWrapper<User>().eq("id", userId));
                    String username = user.getUsername();

                    List<LabelResultDTO> dtoList = new ArrayList<>();
                    for (LabelResult entity : labelResultList) {
                        LabelResultDTO dto = new LabelResultDTO();
                        dto.setResult(entity.getResult());
                        dto.setUsername(username);
                        dtoList.add(dto);
                    }
                    String origins = origin.getSentence();
                    String systemLabel = origin.getSystemLabel();

                    originDTO.setOrigin(origins);
                    originDTO.setSystemLabel(systemLabel);
                    originDTO.setLabeledDto(dtoList);

                    result.put("result",originDTO);
                    return new ResponseUtil<>(HttpStatus.OK, "", result);
                }else {
                    return new ResponseUtil<>(HttpStatus.OK, "originServiceImpl.getOrigin.originStatusFailed");
                }

            } else {
                 this.initOriginRedis(userId,groupId);
                 int size = Math.toIntExact(redisTemplate.opsForList().size(userId + "_" + groupId));
                 if(size>0) {

                     return this.getOrigin(userId, groupId);

                 }else {

                     System.out.println("语料库为空！");
                 }

            }
        }else{

            JSONObject jsonObject = new JSONObject();
            return  new ResponseUtil<>(HttpStatus.OK,"originServiceImpl.getOrigin.need exam",jsonObject);
        }
      return null;
    }

    @Override
    public ResponseUtil<JSONObject> skip(int userId, int groupId){
        // 获取该用户现在的任务并删除
        Integer oldOrigin =redisTemplate.opsForList().leftPop(userId + "_" + groupId);
        if(oldOrigin!=null) {
            // 解锁当前跳过的任务
            originMapper.unLockOrigin(oldOrigin);
            //为跳过的任务标记(要通过3个id同时更新)
            actionMapper.skipOrigin(oldOrigin, userId, groupId);
        }else {
            JSONObject jsonObject = new JSONObject();
            return  new ResponseUtil<>(HttpStatus.OK,"originServiceImpl.skip.unlockFailed",jsonObject);
        }
        // 为用户获取新的任务
        Integer newOrigin = redisTemplate.opsForList().index(userId+"_"+groupId,0);
        if(newOrigin!=null) {
            // 上锁新任务
            originMapper.lockOrigin(newOrigin);
            //如果刚好跳过的是最后一个任务，没有新的任务可分配，就要重新获取语料
        }else {
            return this.getOrigin(userId,groupId);
        }
        return null;
    }

    @Override
    public Boolean deleteOrigin(int userId, int groupId, int originId){
        if(userRoleMapper.selectOne(new QueryWrapper<UserRole>().eq("role_id",1)
                .eq("group_id",groupId)).getUserId().equals(userId)){
//            Origin origin = originService.getById(originId);
//            origin.setActive(false);
//            originService.save(origin);
            originMapper.updateActive(originId);
            return true;
        }else {
            return false;
        }
    }
}


